﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Configuration;
using System.Configuration.Provider;

namespace HomeDmsPageStorageProviders
{
    /// <summary>
    /// All interacting with content of stored pages going through this helper class. It handles
    /// all complexities interacting with final page storage providers 
    /// </summary>
    public static class PageStorage
    {
        private static PageStorageProviderCollection _providers = null;
        private static PageStorageProvider _mainProvider = null;

        private static void LoadProviders()
        {
            if (_providers == null)
            {
                PageStorageProvidersSection section = (PageStorageProvidersSection)ConfigurationManager.GetSection("userSettings/HomeDmsPageStorageProviders");                
                _providers = new PageStorageProviderCollection();
                InstantiateProviders(section.Providers);
                _mainProvider = _providers[section.MainProvider];
                if (_mainProvider == null || !_mainProvider.Active)
                    throw new ProviderException("Unable to load main page storage provider");
            }
        }

        private static void InstantiateProviders(ProviderSettingsCollection providerSettingsCollection)
        {
            foreach (ProviderSettings psettings in providerSettingsCollection)
            {
                PageStorageProvider provider = (PageStorageProvider)InstantiateProvider(psettings);
                _providers.Add(provider);
            }
        }

        private static ProviderBase InstantiateProvider(ProviderSettings providerSettings)
        {
            if ((providerSettings.Type == null) || (providerSettings.Type.Length < 1))
                throw new ConfigurationErrorsException(
                    "Provider could not be instantiated. The Type parameter cannot be null.");

            Type providerType = Type.GetType(providerSettings.Type, true);
            if (providerType == null)
                throw new ConfigurationErrorsException(
                    "Provider could not be instantiated. The Type could not be found.");

            object providerObj = Activator.CreateInstance(providerType);
            if (providerObj == null)
                throw new ConfigurationErrorsException("Provider could not be instantiated.");

            ProviderBase providerBase = ((ProviderBase)providerObj);

            providerBase.Initialize(providerSettings.Name, providerSettings.Parameters);
            return providerBase;
        }

        private static string GetUri(string provider, string guid)
        {
            // TODO:
            // Seems, it is based on db table with columns: guid(string[32]), provider_name[string[30]], uri[string[1000]]. 
            // It has unique index on 1st 2 columns.
            // This method should execute 
            //   Select uri from table where guid = @guid and provider_name = @provider_name
            throw new NotImplementedException();
        }

        private static void SetUri(string provider, string guid, string uri)
        {
            // TODO:
            // Seems, it is based on db table with columns: guid(string[32]), provider-name[string[30]], uri[string[1000]]. 
            // It has unique index on 1st 2 columns.
            // This method should execute 
            //   Insert guid, provider_name, uri into table values (...)
            throw new NotImplementedException();
        }

        private static void DelUri(string guid)
        {
            // TODO:
            // Seems, it is based on db table with columns: guid(string[32]), provider-name[string[30]], uri[string[1000]]. 
            // It has unique index on 1st 2 columns.
            // This method should execute 
            //   Delete from table where guid = @guid
            throw new NotImplementedException();
        }

        public static string CreatePage(string name, byte[] bytes)
        {
            LoadProviders();
            string guid = Guid.NewGuid().ToString("N");
            foreach (PageStorageProvider provider in _providers)
                if (provider.Active)
                {                    
                    string uri = provider.CreatePage(name, bytes);
                    SetUri(provider.Name, guid, uri);
                }
            return guid;
        }

        public static string CreatePage(string name, Image image)
        {
            LoadProviders();
            string guid = Guid.NewGuid().ToString("N");
            foreach (PageStorageProvider provider in _providers)
                if (provider.Active)
                {
                    string uri = provider.CreatePage(name, image);
                    SetUri(provider.Name, guid, uri);
                }
            return guid;
        }

        public static void RetrievePage(string guid, out byte[] bytes)
        {   
            LoadProviders();
            string uri = GetUri(_mainProvider.Name, guid);
            _mainProvider.RetrievePage(uri, out bytes);
        }

        public static void RetrievePage(string guid, out Image image)
        {
            LoadProviders();
            string uri = GetUri(_mainProvider.Name, guid);
            _mainProvider.RetrievePage(uri, out image);
        }

        public static void UpdatePage(string guid, string name, byte[] bytes)
        {
            LoadProviders();
            foreach (PageStorageProvider provider in _providers)
                if (provider.Active)
                {
                    string uri = GetUri(provider.Name, guid);
                    provider.UpdatePage(uri, name, bytes);
                }
        }

        public static void UpdatePage(string guid, string name, Image image)
        {
            LoadProviders();
            foreach (PageStorageProvider provider in _providers)
                if (provider.Active)
                {
                    string uri = GetUri(provider.Name, guid);
                    provider.UpdatePage(uri, name, image);
                }
        }

        public static void DeletePage(string guid)
        {
            LoadProviders();
            foreach (PageStorageProvider provider in _providers)
                if (provider.Active)
                {
                    string uri = GetUri(provider.Name, guid);
                    provider.DeletePage(uri);
                }
            DelUri(guid);
        }

        public static DialogResult ShowConfigurationDialog(string provider, IWin32Window owner)
        {
            LoadProviders();
            foreach (PageStorageProvider p in _providers)
            {
                if (p.Name == provider)
                    return p.ShowConfigurationDialog(owner);
            }
            return DialogResult.Cancel;
        }

        public static PageStorageProviderCollection Providers
        {
            get
            {
                LoadProviders();
                return _providers;
            }
        }

        public static PageStorageProvider MainProvider
        {
            get
            {
                LoadProviders();
                return _mainProvider;
            }
            set
            {
                LoadProviders();
                _mainProvider = value;
            }
        }

        public static void SaveConfiguration()
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            PageStorageProvidersSection section = (PageStorageProvidersSection)config.GetSection("userSettings/HomeDmsPageStorageProviders");
            section.MainProvider = PageStorage.MainProvider.Name;
            foreach (ProviderSettings pset in section.Providers)
                _providers[pset.Name].WriteConfiguration(pset.Parameters);
            config.Save();            
        }
    }
}
